#include "MemPool.h"
#include "aceMesh_clang.h"
#include "aceMesh_utils.h"
#include "am_machine.h"
#include "hashtable.h"
#include "scheduler.h"
#include "slave.h"
#include "task_dag_graph.h"
#include "utils/acelog.h"
unsigned long temp_task[1024];
int tasknum = 0;
extern __thread_local_fix HashMap slave_first_level;
extern __thread_local_fix aceMesh_task *local_parent;
Error_Code register_access(aceMesh_task *task)  // 从核可以使用原子指令保证并发安全
{
    // add_end_task(t);  //延续之前的end
    aceMesh_task *parent = (aceMesh_task *)local_parent;
    if (parent != NULL) {                                           // nested
        slave_setparent(&(task->task_base), &(parent->task_base));  // parent为线程私有变量

        struct TaskDataAccesses *accessStruct = slave_getDataAccesses(&(task->task_base));
        struct TaskDataAccesses *parentAccessStruct = slave_getDataAccesses(&(parent->task_base));

        for (int i = 0; i < accessStruct->_currentIndex; i++) {
            void *address = accessStruct->_addressArray[i];
            struct DataAccess *access = &(accessStruct->_accessArray[i]);
            DataAccessType accessType = access->_type;
            // ReductionInfo *reductionInfo = nullptr;
            struct DataAccess *predecessor = NULL;
            HashMap addresses = parentAccessStruct->_subaccessBottomMap;
            predecessor = (struct DataAccess *)slave_hashGet(addresses, address);  // error出现错误
            // if (predecessor != NULL) {
            //     // Element already exists.
            //     predecessor = entry->_access;
            // }
            slave_hashPut(addresses, address, access);  // error
            struct DataAccess *parentAccess = NULL;
            if (predecessor == NULL) {
                parentAccess = slave_findAccess(&(parent->task_base), address);
                if (parentAccess != NULL) slave_setChild(parentAccess, access);
            } else {
                slave_setSuccessor(predecessor, access);
                // del_end_task(predecessor->_originator);
            }
        }
    } else {  // first level
        slave_setparent(&(task->task_base), NULL);
        struct TaskDataAccesses *accessStruct = slave_getDataAccesses(&(task->task_base));
        for (int i = 0; i < accessStruct->_currentIndex; i++) {
            void *address = accessStruct->_addressArray[i];
            struct DataAccess *access = &(accessStruct->_accessArray[i]);
            DataAccessType accessType = access->_type;
            // ReductionInfo *reductionInfo = nullptr;
            struct DataAccess *predecessor = NULL;
            // bottom_map_t &addresses=first_level;

            bool exist = false;
            exist = slave_hashExists(slave_first_level, address);

            if (exist) {
                // Element already exists.
                predecessor = (struct DataAccess *)slave_hashGet(slave_first_level, address);
            }
            slave_hashPut(slave_first_level, address, access);
            // struct DataAccess *parentAccess = nullptr;
            if (predecessor != NULL) {  // 并发构图需要判断前驱任务是否结束
#ifdef CONCURRENT_CONSTRUCT_GRAPH
                if (predecessor->_originator->over == false) {
                    ((aceMesh_task *)(predecessor->_originator))->mutex_add_successor.lock();
                    if (predecessor->_originator->over == false) {
#endif
                        slave_setSuccessor(predecessor, access);

#ifdef CONCURRENT_CONSTRUCT_GRAPH
                    }
                    ((aceMesh_task *)(predecessor->_originator))->mutex_add_successor.unlock();
                }

#endif
                // del_end_task(predecessor->_originator);        //需要修改
            }
        }
    }
#ifdef CONCURRENT_CONSTRUCT_GRAPH
    if (task->slave_dec_predecessorCount())
#else
    if (slave_predec_count(&(task->task_base)) == -1)  // 从核构造的任务出错
#endif
    {
        //slave_spawn_to_id((struct task *)task);  // slave的是直接spawn，并发场景需要注意！
        temp_task[tasknum] = (unsigned long)task;
        tasknum++;
    }
}

Error_Code register_child_task(aceMesh_task *t)
{
#ifdef NESTOPT
    slave_initprecount(&(t->task_base));
#endif
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    // unsigned long add_start = rpcc();
#endif
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && (defined(FINE_PROF2) || defined(FINE_PROF3))
    unsigned long find_start;
#endif
#ifdef CONCURRENT_CONSTRUCT_GRAPH
    my_mutex_unlock(&(t->task_base.over));
    my_mutex_unlock(&(t->task_base.successor_lock));
    decrement_ref_count(&(t->task_base));
#ifdef NESTOPT
    inc_predecessorCount(&(t->task_base));
#else
    increment_ref_count(&(t->task_base));
#endif
#endif
    // vector_tasks.push_back(t);  // for destroy

    // #if (!defined(SPECIFY_END_TASKS)) || (!defined(NO_END_TASK_LIST))
    // #ifndef NESTOPT
    //     add_end_task(t);
    // #endif
    // #endif
    // #if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    //     buil_prof[END_TASKS_L] += (rpcc() - add_start);
    // #endif

    // #ifdef AUTO_AFFINITY
    //     if (is_master) {
    // #ifdef DISTRIBUTED_SCHEDULER
    //         set_affinity_id(&(t->task_base), total_num_threads);  // modify TODO
    // #else
    //         set_affinity_id(&(t->task_base), MS_SCHED);
    // #endif
    //         is_master = 0;
    // #ifdef DEBUG
    //         printf("register master affinity:%d\n", t->task_base.affinity_id);
    // #endif

    //     } else
    //         set_affinity_id(&(t->task_base), my_affinity.get_affinity_id());
    //         // printf("register affinity:%d\n",t->task_base.affinity_id);
    // #ifdef DEBUG
    // #ifdef SEG_BUFF
    // #ifndef AGENT_COMPU
    //     if (t->task_base.affinity_id == total_num_threads - 1) {
    //         printf("task_affinity error:%d\n", t->task_base.affinity_id);
    //         fflush(stdout);
    //         assert(0);
    //     }
    // #endif
    // #endif
    // #endif
    // #ifdef TEMP_AFFI
    //     t->task_base.bak_affinity_id = t->task_base.affinity_id;
    // #endif
    // #endif

    slave_register_access(t);
    return ACEMESH_OK;
}
Error_Code slave_add_end_task_of_parent()  // serial
{
    if (local_parent != NULL) {
        struct TaskDataAccesses *parentAccessStruct = slave_getDataAccesses(
            &(((aceMesh_task *)
                  local_parent)->task_base));  // 遍历父任务中的哈希表，最后一层与父任务建边
        HashMap addresses = parentAccessStruct->_subaccessBottomMap;
        HashMapIterator itr = slave_createHashMapIterator(addresses);
        // while (slave_hasNextHashMapIterator(itr)) {
        //     itr = slave_nextHashMapIterator(itr);

        // }
        for (int index = 0; hasNextHashMapIterator(itr);
             index++) {  // 这个地方最后一层子任务与父任务建边是为了向后继父任务传递依赖关系。
            // 迭代取出所有键值对
            itr = nextHashMapIterator(itr);
           // slave_setSuccessor(predecessor, itr->entry->value);
        }
    }
}
Error_Code slave_spawn_and_goout()
{
    //    this->spawn();
    // this->reset_task_graph();
    // slave_add_end_task_of_parent();
    // slave_hashClear(slave_first_level);
printf("begin spawn\n");    
for (int i = 0; i < tasknum; i++) {
        slave_spawn_to_id((struct task *)temp_task[i]);
    }
    return ACEMESH_OK;
}

Error_Code slave_spawn_and_wait() {}
